#! /bin/bash
#
# bin/build-cursors
# Part of ComixCursors, a desktop cursor theme.
#
# Copyright © 2010–2013 Ben Finney <ben+opendesktop@benfinney.id.au>
# Copyright © 2006–2013 Jens Luetkens <j.luetkens@limitland.de>
#
# This work is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This work is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this work. If not, see <http://www.gnu.org/licenses/>.

# Create the cursor image files from SVG source.

THEMENAME="${THEMENAME:-Custom}"
export THEMENAME
ORIENTATION="${ORIENTATION:-RightHanded}"
export ORIENTATION

bindir="$(dirname $0)"

themename_stem="ComixCursors"
configfile_dir="${themename_stem}Configs"
configfile="${configfile_dir}/${THEMENAME}.CONFIG"
theme_template="${configfile_dir}/${themename_stem}.theme"

# source the theme config file
source "${configfile}"
if [ ${THEMEINCLUDE} ] ; then
    source "${configfile_dir}/${THEMEINCLUDE#-}.INCLUDE"
fi

SHADOWOPAQ=$(echo "1 - $SHADOWTRANS" | bc | sed 's/^\./0\./' | sed 's/\.0$//')
CURSOROPAQ=$(echo "1 - $CURSORTRANS" | bc | sed 's/^\./0\./' | sed 's/\.0$//')

function svg_substitutions {
    # Process an SVG file with custom substitutions.
    local infile="$1"

    substitutions=(
        "s/#000000/$OUTLINECOLOR/g"
        "s/stroke-width:20/stroke-width:$OUTLINE/g"
        "s/#999999/$CURSORCOLORHI/g"
        "s/#555555/$CURSORCOLORLO/g"
        "s/#999933/$HILIGHTHI/g"
        "s/#666600/$HILIGHTLO/g"
        "s/#010101/$HAIR/g"
        "s/#111111/$SHADOWCOLOR/g"
        "s/opacity:0.15/opacity:$SHADOWOPAQ/g"
        "s/opacity:0.75/opacity:$CURSOROPAQ/g"
        )

    sed $(for subst in "${substitutions[@]}" ; do printf " -e ${subst}" ; done) \
        "$infile"
}

function svg_rotate {
    # Apply rotation angle.
    local infile="$1"
    local angle="$2"

    sed \
        -e "s/rotate(0,/rotate($angle,/" \
        "$infile"
}

svgdir="svg"

indir="${svgdir}/${ORIENTATION}"
workdir="tmp"
builddir="build"
xcursor_builddir="cursors"
export workdir builddir

mkdir --parents "${builddir}"
mkdir --parents "${workdir}"
mkdir --parents "${xcursor_builddir}"

# Copy the HOTSPOTS file to the working directory.
hotspots_file="${indir}/HOTSPOTS"
cp "$hotspots_file" "$workdir"/.

function generate_theme {
    # Process the theme file.
    local name="$1"
    local sizename="${SIZENAME//-/ }"
    xcursor_theme="${builddir}/${name}.theme"
    custom_theme="ComixCursorsConfigs/${name}.theme"
    themename=${name//-/ }
    if [[ $ORIENTATION == "LeftHanded" ]] ; then
        facing=" left-handed"
    else
        facing=""
    fi

    variation=" ${THEMEINCLUDE#-}" && [ -v ${THEMEINCLUDE} ] && variation=""
    variation=${variation//-/ }

    if [ -f "$custom_theme" ] ; then
        sed "s/THEMENAME/$themename/g" "$custom_theme" | sed "s/ORIENTATION/$facing/g" | sed "s/SIZENAME/$sizename/g" | sed "s/VARIATION/$variation/g" > "$xcursor_theme"
    elif [ -f "$theme_template" ] ; then
        sed "s/THEMENAME/$themename/g" "$theme_template" | sed "s/ORIENTATION/$facing/g" | sed "s/SIZENAME/$sizename/g" | sed "s/VARIATION/$variation/g" > "$xcursor_theme"
    fi
}

function generate_animation_source_frames {
    # Generate the source frame images for an animation.
    local name="$1"
    local frames_count=$2

    first_frame_file="${indir}/${name}.svg"
    for frame in $(seq --equal-width 1 $frames_count) ; do
        frame_file="${indir}/${name}.frame${frame}.svg"
        case $frame in
            1)
                cp "$first_frame_file" "$frame_file"
                ;;
            *)
	            angle=$(echo "360 / $frames_count * ($frame - 1)" | bc)
                svg_rotate "$first_frame_file" $angle > "$frame_file"
                ;;
        esac
    done
}

function render_cursor_image {
    # Render SVG source image to finished PNG image.
    local name="$1"
    local compose_opts="$2"
    local frame=$3
    local frame_duration=$4

    compose_opts="${compose_opts} --orientation $ORIENTATION"

    if [[ "$frame" ]] ; then
        image_name="${name}.frame${frame}"
        compose_opts="${compose_opts} --frame $frame"
        if [[ "$frame_duration" ]] ; then
            compose_opts="${compose_opts} --duration $frame_duration"
        fi
    else
        frame=0
        image_name="${name}"
    fi

    infile="${indir}/${image_name}.svg"
    if [[ ! -f "$infile" ]] ; then
        echo "skipping $name; no svg file found."
        return 1
    fi
    tempfile="${workdir}/$(basename $infile)"
    outfile="${builddir}/${image_name}.png"
    svg_substitutions "$infile" > "$tempfile"
    "${bindir}"/render-cursor-image $compose_opts "$name" "$tempfile" "$outfile"
}

## Generate the theme file. Process the size argument only if the
## configuration has only one SIZES() item.
#if [ ${#SIZES[@]} -eq 1 ]; then
#    sizename=${SIZES[0]%%=*}
#fi

generate_theme "$THEMENAME"

# the basic cursors
names="
all-scroll
cell
col-resize
crosshair
default
e-resize
ew-resize
grabbing
n-resize
ne-resize
nesw-resize
not-allowed
ns-resize
nw-resize
nwse-resize
pencil
pirate
pointer
right-arrow
row-resize
s-resize
se-resize
sw-resize
text
up-arrow
vertical-text
w-resize
X-cursor
zoom-in
zoom-out
alias
context-menu
copy
move
no-drop
"

for name in $names ; do
    compose_opts=""
    render_cursor_image "$name" "$compose_opts"
done

# the animated cursors

name="help"
compose_opts=""
frames_count=2
generate_animation_source_frames "$name" $frames_count
render_cursor_image "$name" "$compose_opts" 1 2000
render_cursor_image "$name" "$compose_opts" 2 500

name="progress"
frames_count=24
generate_animation_source_frames "$name" $frames_count
for frame in $(seq --equal-width 1 $frames_count) ; do
    compose_opts=""
    render_cursor_image "$name" "$compose_opts" $frame
done

name="wait"
frames_count=36
generate_animation_source_frames "$name" $frames_count
for frame in $(seq --equal-width 1 $frames_count) ; do
    compose_opts=""
    render_cursor_image "$name" "$compose_opts" $frame
done
